package org.example.sec11.interceptors.server;

import io.grpc.*;
import org.example.sec11.Constants;

import java.util.Objects;
import java.util.Set;

public class UserTokenInterceptor implements ServerInterceptor {
    //管理员 所有都能访问
    private static final Set<String> IS_SET = Set.of("1", "2", "3");
    //普通用户 服务端流不允许 其他可以
    private static final Set<String> NOT_SET = Set.of("4", "5", "6");

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
        String s = headers.get(Constants.USER_TOKEN_KEY);
        String token = extractToken(s);
        if (!isValid(token)) {
            return close(call, headers, Status.UNAUTHENTICATED.withDescription("token is null"));
        }
        //判断当前RPC方法类型是否允许服务器只发送一条消息。
        //如果当前RPC方法类型是 UNARY 或 CLIENT_STREAMING，返回 true
        boolean isOneMessage = call.getMethodDescriptor().getType().clientSendsOneMessage();
        if (isOneMessage || IS_SET.contains(token)) {
            return next.startCall(call, headers);
        }

        return close(call, headers, Status.PERMISSION_DENIED.withDescription("user is not allowed to do this operation"));
    }

    private <ReqT, RespT> ServerCall.Listener<ReqT> close(ServerCall<ReqT, RespT> call, Metadata headers, Status status) {
        call.close(status, headers);
        return new ServerCall.Listener<ReqT>() {
        };
    }

    private boolean isValid(String token) {
        return Objects.nonNull(token) && (IS_SET.contains(token) || NOT_SET.contains(token));
    }

    private String extractToken(String value) {
        return Objects.nonNull(value) && value.startsWith(Constants.BEARER) ? value.substring(Constants.BEARER.length()).trim() : null;
    }
}
